package myJs.user

import myJs.Utils._
import org.scalajs.dom.{Element, _}
import scalatags.Text.{TypedTag, all}
import scalatags.Text.all.{value, _}

import scala.scalajs.js
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import myJs.tool.Tool.{layerOptions, myElement, zhInfo}
import myJs.myPkg._

import scala.scalajs.js.{Date, JSON}
import myJs.myPkg.jquery._
import org.scalajs.dom.ext.Ajax

import scala.concurrent.ExecutionContext.Implicits.global
import myJs.Implicits._
import shared.VarTool

import scala.scalajs.js.JSConverters._
import scala.collection.immutable.SeqMap
import myJs.myPkg.bootstrap.Bootstrap.default._
import myJs.tool.Tool
import org.scalajs.dom.raw.{Blob, BlobPropertyBag}
import scala.scalajs.js.Dynamic.{global => g}

/**
 * Created by yz on 2019/4/25
 */
@JSExportTopLevel("DatExport")
object DatExport {

  val typeTagEmpty = List[TypedTag[String]]()
  val tableId = "missionTable"
  val kind = VarTool.batchMissionStr

  @JSExport("init")
  def init = {
    bootStrapValidator

  }

  @JSExport("myRun")
  def myRun = {
    val bv = jQuery("#form").data("bootstrapValidator")
    bv.validate()
    val valid = bv.isValid().toB
    if (valid) {
      val formData = new FormData(document.getElementById("form").toHTMLFormElement)
      $(":disabled").attr("disabled", false)
      val element = div(id := "content",
        span(id := "info", "正在运行",
          span(id := "progress", "。。。")), " ",
        img(src := "/assets/images/running2.gif", cls := "runningImage", width := 30, height := 20)
      ).render
      val layerOptions = LayerOptions.title(zhInfo).closeBtn(0).skin("layui-layer-molv").btn(js.Array())
      val index = layer.alert(element, layerOptions)
      val url = g.jsRoutes.controllers.DatController.xml2Dat().url.toString
      val xhr = new XMLHttpRequest
      xhr.open("post", url)
      xhr.upload.onprogress = progressHandlingFunction
      xhr.onreadystatechange = (e) => {
        if (xhr.readyState == XMLHttpRequest.DONE) {
          val data = xhr.response
          layer.close(index)
          Tool.downloadTxt("out.dat", xhr.response)
        }
      }
      xhr.send(formData)
    }
  }

  def bootStrapValidator = {
    val url = g.jsRoutes.controllers.MissionController.missionNameCheck().url.toString
    val maxNumber = Double.MaxValue
    val dict = js.Dictionary(
      "feedbackIcons" -> js.Dictionary(
        "valid" -> "glyphicon glyphicon-ok",
        "invalid" -> "glyphicon glyphicon-remove",
        "validating" -> "glyphicon glyphicon-refresh",
      ),
      "fields" -> js.Dictionary(
        "xmlFile" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "xml文件不能为空!"
            ),
            "file" -> js.Dictionary(
              "message" -> "xml文件格式不正确!",
              "extension" -> "xml",
            ),
          )
        ),

      )
    )
    g.$("#form").bootstrapValidator(dict)

  }


  val operateColumn = js.Array(
    ColumnOptions.field("操作").title("操作").formatter(operateFmt))

  def tbFmt(columnName: String): js.Function = (v: js.Any, row: js.Dictionary[js.Any]) => columnName match {
    case "missionName" => {
      val rs = if (row("missionIntro").toString.nonEmpty) {
        val dict = row("missionIntro")
        span(v.toString, title := dict.toString)
      } else {
        span(v.toString)
      }
      rs.render
    }
    case "state" => {
      val state1 = if (List("success").contains(row("state"))) {
        span(cls := "label label-success", "成功！")
      } else if (List("running").contains(row("state"))) {
        span("正在运行 ",
          img(cls := "runningImage", src := "/assets/images/running2.gif", width := 30, height := 20))
      } else if (List("wait", "preparing").contains(row("state"))) {
        span(
          span(cls := "label label-default", "排队中 "),
          all.raw("&nbsp;"),
          img(cls := "runningImage", src := "/assets/images/running2.gif", width := 30, height := 20))
      } else {
        span(cls := "label label-danger", "错误！")
      }
      state1.toString()
    }

    case _ => v
  }

  def initTable = {
    val tableId = "missionTable"
    val map = SeqMap("missionName" -> "分析名称", "missionIntro" -> "分析描述", "state" -> "运行状态",
      "startTime" -> "开始日期", "endTime" -> "结束日期")
    val columnNames = map.keyList
    val columns = columnNames.map { columnName =>
      val title = map.getOrElse(columnName, columnName)
      val fmt = MissionManage.tbFmt(columnName)
      val basicOptions = ColumnOptions.field(columnName).title(title).sortable(true).formatter(fmt)
      val datepickerOptions: js.Dictionary[js.Any] = js.Dictionary("format" -> Tool.pattern, "language" -> "zh-CN",
        "autoclose" -> true)
      columnName match {
        case "missionName" =>
          basicOptions.filterControl("input")
        case "missionIntro" => basicOptions.filterControl("input")
        case "startTime" => basicOptions.filterControl("datepicker").filterCustomSearch(timeAfter).
          filterControlPlaceholder("开始").filterDatepickerOptions(datepickerOptions)
        case "endTime" => basicOptions.filterControl("datepicker").filterCustomSearch(timeBefore).
          filterControlPlaceholder("截止").filterDatepickerOptions(datepickerOptions)
        case _ => basicOptions
      }
    }.concat(operateColumn)
    val options = TableOptions.columns(columns.toJSArray).searchOnButton(false).filterControl(false)
    $(s"#${tableId}").bootstrapTable(options)
  }

  @JSExport("clearSearch")
  def clearSearch = {
    $(".filter-control input").`val`("")
    $(s"#${tableId}").bootstrapTable("triggerSearch")
  }

  @JSExport("toggleSearch")
  def toggleSearch = {
    val filterControlNonExist = $(".filter-control").length == 0
    $(s"#${tableId}").bootstrapTable("refreshOptions", TableOptions.filterControl(filterControlNonExist))
  }

  @JSExport("refreshMission")
  def refreshMission(f: () => Any = () => ()) = {
    val url = g.jsRoutes.controllers.MissionController.getAllMission().url.toString
    Ajax.get(url = s"${url}?kind=${kind}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
      val data = xhr.responseText.toJArJDS
      $("#missionTable").bootstrapTable("load", data)
      f()
    }
  }

  @JSExport("timeAfter")
  def timeAfter: js.Function = {
    (text: String, value: String, field: String, data: js.Array[js.Dictionary[String]]) => {
      val date = new Date(text)
      val dbDate = new Date(value)
      dbDate.setUTCHours(0, 0, 0, 0)
      date.getTime() <= dbDate.getTime()
    }
  }

  def timeBefore: js.Function = {
    (text: String, value: String, field: String, data: js.Array[js.Dictionary[String]]) => {
      val date = new Date(text)
      val dbDate = new Date(value)
      dbDate.setUTCHours(0, 0, 0, 0)
      date.getTime() >= dbDate.getTime()
    }
  }

  @JSExport("operateFmt")
  def operateFmt: js.Function = {
    (v: js.Any, row: js.Dictionary[js.Any]) =>
      val deleteStr = a(
        title := "删除",
        cursor.pointer,
        onclick := s"MissionManage.deleteData('" + row("id") + "')",
        target := "_blank",
        span(
          em(cls := "fa fa-close")
        )
      )

      val viewStr = a(title := "日志", onclick := s"MissionManage.viewLog('${row("id")}')", cursor.pointer,
        span(em(cls := "fa fa-file-text"))
      )

      val detailUrl = g.jsRoutes.controllers.MissionController.missionSummaryBefore().url.toString
      val detailStr = a(title := "详情", href := s"${detailUrl}?missionId=${row("id")}", cursor.pointer, target := "_blank",
        span(em(cls := "fa fa-eye"))
      )

      val state1 = if (List("success").contains(row("state"))) {
        List(detailStr)
      } else List[TypedTag[String]]()
      val state2 = if (!List("running").contains(row("state"))) {
        List(viewStr)
      } else List[TypedTag[String]]()
      val rs = state1 ::: state2 ::: List(deleteStr)
      rs.mkString("&nbsp;")

  }

  @JSExport("search")
  def search = {
    val parentStr = "#search"
    val data = $(s"${parentStr} #form").serialize()
    val formData = new FormData($(s"${parentStr} #form")(0).toHTMLFormElement)
    val url = g.jsRoutes.controllers.MissionController.search().url.toString
    val index = layer.alert(Tool.myElement, layerOptions)
    Ajax.post(url = s"${url}", data = formData, responseType = "application/json").map { xhr =>
      val rs = xhr.responseText.toJArJDS
      $(s"#${tableId}").bootstrapTable("destroy").bootstrapTable(TableOptions.data(rs))
      layer.close(index)
    }
  }

  @JSExport("viewLog")
  def viewLog(id: String) = {
    val url = g.jsRoutes.controllers.MissionController.getLogContent().url.toString
    Ajax.get(url = s"${url}?missionId=${id}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
      val data = xhr.response
      val options = LayerOptions.`type`(1).title("<h4>运行信息</h4>").area(js.Array("900px", "600px")).
        skin("layui-layer-demo").closeBtn(1).anim(2).shadeClose(true).maxmin(true).
        content(s"<pre style='word-wrap: break-word' class='genome-pre'>${data}</pre>")
      layer.open(options)
    }
  }

  def updateMissionSocket = {
    val url = g.jsRoutes.controllers.MissionController.updateMissionSocket(kind).url.toString
    val wsUri = s"ws://${window.location.host}${url}"
    webSocket(wsUri)
  }

  def webSocket(wsUri: String) = {
    val websocket = new WebSocket(wsUri)
    websocket.onopen = (evt) =>
      websocket.send(JSON.stringify(js.Dictionary("info" -> "start")))
    websocket.onclose = (evt) =>
      println(s"ERROR:${evt.code},${evt.reason},${evt.wasClean}")
    websocket.onmessage = (evt) => {
      val message = evt.data
      val data = JSON.parse(message.toString).toJDS
      $("#missionTable").bootstrapTable("load", data)
    }
    websocket.onerror = (evt) => {
      updateByHand
      println(s"ERROR:${evt.toString}")
    }
  }

  def updateByHand = {
    js.timers.setInterval(3000) {
      refreshMission()
    }
  }


}
